/*
 * adc_drv.c
 *
 * Created: 13.08.2012 12:17:20
 *  Author: Timmo
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>

#include "adc_drv.h"
#include "settings.h"

uint8_t ReadCalibrationByte( uint8_t index ){
	uint8_t result;

	/* Load the NVM Command register to read the calibration row. */
	NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
	result = pgm_read_byte(index);

	/* Clean up NVM Command register. */
	NVM_CMD = NVM_CMD_NO_OPERATION_gc;

	return( result );
}


void ADC_init(){
	//PORTA.DIRCLR = ;
	
	//Read factory calibration bytes
	ADCA.CALL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) );
	ADCA.CALH = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) );
	
	//Start in signed free running mode with 12 Bit resolution
	ADCA.CTRLB = ADC_CONMODE_bm | ADC_RESOLUTION_12BIT_gc | ADC_FREERUN_bm | ADC_CURRLIMIT_LARGE_gc;  //Save some power by reducing the max sample rate
	if(mt_settings.PCB_Revision > 9)
		ADCA.REFCTRL = ADC_REFSEL_AREFA_gc;
	else
		ADCA.REFCTRL = ADC_REFSEL_INT1V_gc;
	ADCA.PRESCALER = ADC_PRESCALER_DIV32_gc;	// => 125kHz
	
	//Sweep through Channel 0-2
	ADCA.EVCTRL = ADC_SWEEP_012_gc;

	ADCA.CTRLA = ADC_ENABLE_bm; // ADCA Enable
	ADCA.CH0.CTRL |= ADC_CH_INPUTMODE_SINGLEENDED_gc;
	ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc;
	ADCA.CH1.CTRL |= ADC_CH_INPUTMODE_SINGLEENDED_gc;
	ADCA.CH1.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc;	
	ADCA.CH2.CTRL |= ADC_CH_INPUTMODE_SINGLEENDED_gc;
	ADCA.CH2.MUXCTRL = ADC_CH_MUXPOS_PIN1_gc;
	//ADC_calibrate_offset();
}


int16_t ADC_read_ch0(void){
	int16_t temp;
	while(!ADCA.CH0.INTFLAGS);
	/* read 16 bit value atomic to prevent 
	 * reading is interrupted by timer ISR
	 */
	cli();
	temp = ADCA.CH0.RES;
	sei();
	ADCA.CH0.INTFLAGS = 1; //Clear Flag
	
	return temp;
	
}


int16_t ADC_read_ch1(void){
	int16_t temp;
	while(!ADCA.CH1.INTFLAGS);
	/* read 16 bit value atomic to prevent 
	 * reading is interrupted by timer ISR
	 */
	cli();
	temp = ADCA.CH1.RES;
	sei();
	ADCA.CH1.INTFLAGS = 1; //Clear Flag
	
	return temp;
	
}

int16_t ADC_read_ch2(void){
	int16_t temp;
	while(!ADCA.CH2.INTFLAGS);
	/* read 16 bit value atomic to prevent 
	 * reading is interrupted by timer ISR
	 */
	cli();
	temp = ADCA.CH2.RES;
	sei();
	ADCA.CH2.INTFLAGS = 1; //Clear Flag
	return temp;
}




